/**
 * Created by scenic on 2017/8/10.
 */
import {SpaceFace} from "./SpaceFace";
import {Space} from "./Space";
import {MeshCreateUtils as MeshCreateUtis} from "./MeshCreateUtils";
import {UpdateSegmentInterfaceForBox} from "./BusyLogic";

var DEBUG = false;

function BoxSpace(width, height, depth) {
    Space.call(this, width, height, depth);

    this.faces = [
        new SpaceFace(this, "右"),
        new SpaceFace(this, "左"),
        new SpaceFace(this, "上"),
        new SpaceFace(this, "底"),
        new SpaceFace(this, "前"),
        new SpaceFace(this, "后"),
    ]

    var scope = this;
    this.faces.forEach(function (f) {
        f.getAssociateMesh().setName(scope.name + "-" + f.name);
    })
    this.faces[4].associatePlank.isDoor = true;
    var materials = [];
    for (var i = 0; i < 6; i++) {
        var material = new THREE.MeshLambertMaterial({
            transparent: true,
            opacity: 0.4,
            color: Math.random() * 0xffffff,
            depthTest: true
        });
        materials.push(material);
    }
    this.spaceMesh = new GSThree.Mesh(new THREE.BoxBufferGeometry(MeshCreateUtis.defaultWidth, MeshCreateUtis.defaultHeight, MeshCreateUtis.defaultDepth), materials).setName(this.name);
    //产品的尺寸
    this.dimension = new THREE.Vector3(width != undefined ? width : MeshCreateUtis.defaultWidth, height != undefined ? height : MeshCreateUtis.defaultHeight, depth != undefined ? depth : MeshCreateUtis.defaultDepth);

    // this.spaceMesh.raycastSensitivity = false;


    Object.defineProperty(this, "rightFace", {
        get: function () {

            return this.faces[0];
        },

    });
    Object.defineProperty(this, "leftFace", {
        get: function () {
            return this.faces[1];
        },

    });
    Object.defineProperty(this, "topFace", {
        get: function () {
            return this.faces[2];
        },

    });
    Object.defineProperty(this, "bottomFace", {
        get: function () {
            return this.faces[3];
        },

    });
    Object.defineProperty(this, "frontFace", {
        get: function () {
            return this.faces[4]
        },

    });
    Object.defineProperty(this, "backFace", {
        get: function () {
            return this.faces[5]
        },

    });

    this.updateSegmentInterface = new UpdateSegmentInterfaceForBox();
}
BoxSpace.prototype = Object.assign(Object.create(Space.prototype), {
    constructor: BoxSpace,

    calculateFreeSpace:function () {
        var spaceFreeDimension = this.dimension.clone();
        this.faces.forEach(function (face) {
            if (!face.associatePlank.isDoor) {
                var thickness = face.getAssociateThickness();
                var offset = new THREE.Vector3(thickness, thickness, thickness);
                offset.multiply(face.normal).positive();
                spaceFreeDimension.sub(offset);
            }
        })
        return spaceFreeDimension;

    },

    /**
     * 根据父空间的线性分割和分割方向，更新子空间的空间信息
     */
    updateSegment: function () {

        var directionNormal = this.segmentOrientation;
        var segmentValue = this.segment;
        if (segmentValue == undefined || directionNormal == undefined) {
            console.warn("GSBuilder　:　the segment of segmentOrientation undefined")
            return;
        }
        var updateSegmentInterface = this.updateSegmentInterface;
        var scope = this;

        var freeChildrenSpaceIndex = 0;
        var children = this.children_space;

        function getCachedOrCreateChildrenSpace() {
            var space;
            if (freeChildrenSpaceIndex < children.length) {
                space = children[freeChildrenSpaceIndex];
            }
            if (space == undefined) {
                space = new BoxSpace();
                scope.add(space);
            }
            freeChildrenSpaceIndex++;
            return space;
        }

        //计算剩余的空间
        this.updateSpaceMeshAndFaces();
        var spaceFreeDimension = updateSegmentInterface.calculateFreeSpace.call(scope, this);

        if (DEBUG) {
            console.log("spaceFreeDimension is ");
            console.log(spaceFreeDimension);
        }

        //在给定分割方向的尺寸的投影向量
        var dimensionProject = new THREE.Vector3().copy(spaceFreeDimension).projectOnVector(directionNormal).errorNegativeValue();

        if (DEBUG) {
            console.log("dimensionProject is ");
            console.log(dimensionProject);
        }

        //减去投影后的尺寸
        var dimensionResidue = new THREE.Vector3().copy(spaceFreeDimension).sub(dimensionProject);

        if (DEBUG) {
            console.log("dimensionResidue is ");
            console.log(dimensionResidue);
        }

        //更新尺寸
        var segmentRates = GSThree.CommonUtils.parseProportion(this.segment);
        for (var i = 0; i < segmentRates.length; i++) {
            var childSpace = getCachedOrCreateChildrenSpace();
            var segmentRate = segmentRates[i];
            //首先总的空间要减去再分割方向的分量，然后加上计算之后的分割方向的分量

            childSpace.dimension.copy(dimensionResidue)
            //加上在分割方向的计算完成的新的分量
                .add(dimensionProject.clone().multiplyScalar(segmentRate));
            if (DEBUG) {
                console.log("children dimension :");
                console.log(childSpace.dimension)
            }
        }

        var firstChildrenPosition = updateSegmentInterface.calculateFirstChildSpacePosition.call(scope, spaceFreeDimension);

        //更新位置
        var lastSpace = undefined;
        for (var i = 0; i < children.length; i++) {
            var space = children[i];
            if (lastSpace == undefined) {
                //计算第一个空间的位置
                space.position.copy(firstChildrenPosition);
            } else {
                //后面的空间都需要根据第一个空间进行偏移

                space.position.copy(lastSpace.position)
                    .add(lastSpace.getHalfDimensionInDirection(directionNormal))
                    .add(space.getHalfDimensionInDirection(directionNormal));

            }
            if (DEBUG) {
                console.log("position of children " + i);
                console.log(space.position);
                console.log("dimension is ");
            }
            lastSpace = space;
        }

        //更新孩子的mesh信息
        this.traverse(function () {
            this.updateSpaceMeshAndFaces();
        })
    },

    /**
     * 根据空间几何体面的信息，最简单的设置木板的位置
     */
    updatePlankByMesh: function () {
        this.faces.forEach(function (face) {
            face.updatePlankByBaseGraphic();
        })
    },

    /**
     * 更新木板位置的默认的算法
     */
    updatePlankDimensionWidthDefault: function () {
        this.updatePlankByMesh();
        function sub(p1, p2) {
            p1.forEach(function (face1) {
                p2.forEach(function (face2) {
                    var normal = face2.geometryFaces[0].normal;
                    var thickness = face2.getAssociateThickness();
                    face1.getAssociateMesh().holdEdgesScale(normal, -thickness);
                });
            });

        }

        sub([this.topFace, this.bottomFace], [this.leftFace, this.rightFace]);
        sub([this.frontFace, this.backFace], [this.leftFace, this.rightFace]);
        sub([this.frontFace, this.backFace], [this.topFace, this.bottomFace]);

    },

    updatePlankDoor: function () {
        var scope = this;
        var parent = this.parent;
        this.faces.forEach(function (face) {
            if (face.associatePlank.isDoor) {
                //如果当前的面是门板
                var thickness = face.getAssociateThickness();
                console.log("update plank door " + thickness);
                if (parent != null) {
                    //是子空间的门板
                    if (DEBUG) {
                        console.log("The space dimension before scale ");
                        console.log(scope.position.clone());
                        console.log(scope.dimension.clone());
                    }
                    scope.updateSpaceMeshAndFaces();
                    scope.getAssociateMesh().holdEdgesScale(new THREE.Vector3(0, 0, 1), -thickness);
                    scope.position.copy(scope.getAssociateMesh().position.errorNaNOrInfinity());
                    scope.dimension.copy(scope.getAssociateMesh().getDimension().errorNaNOrInfinity());
                    scope.updateSpaceMeshAndFaces();

                    //尺寸变化了，应该更新先行分割，来更新孩子空间的信息
                    scope.updateSegment();
                    if (DEBUG) {
                        console.log("The space dimension after scale ");
                        console.log(scope.position.clone());
                        console.log(scope.dimension.clone());
                    }
                    //空间改变了，所有的面对应的板材需要更新
                    scope.updatePlankDimensionWidthDefault();
                }
                face.updatePlankByBaseGraphic();
                face.getAssociateMesh().position.addScaledVector(face.normal, thickness);
            }
        })
    },

    /**
     * 侧板，顶板，底板开槽
     */
    updatePlankBackPlankSlot:function () {
        var slotDeep = 10;


    },

    updateSpaceMeshMaterial: function () {
        var material = this.spaceMesh.material;
        this.faces.forEach(function (face) {
            var materialIndex = face.geometryFaces[0].materialIndex;
            material[materialIndex].visible = !face.getAssociateMesh().isAddToScene;
        })

    },

    getHalfDimensionInDirection: function (directionNormal) {
        //返回值有可能是负数，因为反方向风格的话，是需要负数的
        return this.dimension.clone().multiply(directionNormal).multiplyScalar(0.5);
    },

    updatePlankOffset:function () {
        this.faces.forEach(function (f) {
            var plank = f.associatePlank;
            var offset = plank.positionOffset;
            var mesh = f.getAssociateMesh();
            mesh.position.add(offset);
        })
    }

})
export {BoxSpace};